#include "udef.h"
#include "io.h"

#include "udefcg.h"
#include "sortcg.h"
#include "hop_sort.h"
#include "udef_stat.h"
#include "cgmmap.h"




extern char *__progname;


void
usage(void) 
{
	fprintf(stderr, "Usage: %s [-pbsmrih -c ncyl] device\n", __progname);
	fprintf(stderr, "  -c x: select cylinder x\n");
	fprintf(stderr, "  -p: print cg block info\n");
	fprintf(stderr, "  -b: print blocks bitmap\n");
	fprintf(stderr, "  -s: print slink\n");
	fprintf(stderr, "  -m: use memory for whole cg\n");
	fprintf(stderr, "  -r: run defragmentation\n");
	fprintf(stderr, "  -i: hop sort mode\n");
	fprintf(stderr, "  -h: print this help\n");
	
	exit(1);
}


int 
main(int argc, char *argv[])
{
	int 	fd = 0;
	uint 	ncyl = 0; 			/* cislo cylindru */
	int 	rflag = 0;			/* vypsat info */
	int		pflag = 0;			/* nacte a vytiskne blockap */
	int 	sflag = 0;			/* vypsat slink */
	int		bflag = 0;			/* vytiskne bitmapu blksused */
	int 	mflag = 0;			/* memory flag - cgmmap */
	int 	iflag = 0;			/* insecure - moznost ztraty dat */
	int 	ch;
	GLBVAL 	glb;				/* obsahuje "globalni" prom */
	
#if MEASURE
	struct timeval tm1;
	struct timeval tm2;
#endif	
	
	cgun  aacg;
	struct cg *acg = (struct cg *) &(aacg.cg);
	
	bzero(&glb, sizeof(GLBVAL));
	glb.acg = acg;
		
	if (argc < 2) {
		usage();
	}
	
#if MEASURE
	if (gettimeofday(&tm1, NULL) != 0)
		perror("MEASURE 1 error:");
#endif	
	
	/* XXX nekontroluju vstup - atoi */
	while ((ch = getopt(argc, argv, "hrpsmbic:")) != -1) {
		switch (ch) {
			case 'c':
				ncyl = (unsigned int) atoi(optarg);
				break;
			case 'r':
				rflag = 1;
				break;		
			case 'p':
				pflag = 1;
				break;
			case 's':
				sflag = 1;
				break;				
			case 'b':
				bflag = 1;
				break;		
			case 'm':
				mflag = 1;
				break;
			case 'i':
				iflag = 1;
				break;				
			case 'h':
			default:
				usage();
				break;
		}
	}
	argc -= optind;
	argv += optind;

	/* otevru zarizeni a nactu superblock */
	if ((fd = open_disk(argv[0])) == -1)
		return 1;
		
	glb.fd = fd;
	
	/* mmap pro cyl group */
	if (mflag) {
		if (cgmmap(&glb, ncyl)) {
			close(glb.fd);
			return 1;
		}
	}
	
	if (read_cgblock(&glb, &(glb.acg), ncyl)) {
		close(glb.fd);
		return 1;
	}
	
	/* insecure mod */
	if (iflag)
		glb.flags |= GLBRUNINSEC;
		
	/* vypisu jako def, bez parametru  */
	print_sblock();
	print_cgblock(glb.acg, ncyl);
	print_inodes(&glb);
	
	/* vypise bitmapu */
	if (bflag)
		print_bmap(glb.acg, afs.fs_fpg);
		
	if (sflag && !(rflag || pflag))
		fprintf(stderr, "Use -s with parametr -r or -p\n");
		

	if (rflag || pflag) {
		if (udefcg(&glb, ncyl))
			return 1;
		
		print_blockap(&glb);
		
		if (sflag)
			print_slink(&glb);
			
		if (rflag)
			sortcg(&glb);
	}
	
	
	/* UKONCENI, uzavreni a dealokace ! */
	free_blockap(&glb);
	free_slink(&glb);
	
	if (glb.flags & GLBCGISMMAP)
		cgm_unmap(&glb);
		
	close(fd);
	
#if MEASURE
	if (gettimeofday(&tm2, NULL) != 0)
		perror("MEASURE 2 error:");
	else {
		double ts1=tm1.tv_sec+(tm1.tv_usec/1000000.0);
		double ts2=tm2.tv_sec+(tm2.tv_usec/1000000.0);
		fprintf(stderr, "%.6lf seconds elapsed\n", ts2-ts1);
	}
#endif	
	
	return 0; /* ;-) */
}
